package cn.gene.timeyan.chat.socket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 小锥子*
 *
 * @author LWG
 * @date 2022/8/14 19:23
 * @since 1.0.0 @gene.cn
 */
@Component
@Slf4j
@Service
@ServerEndpoint("/api/websocket/{user}/{id}")
public class WebSocketServer {
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static Map<Object, Session> adminHashMap = new ConcurrentHashMap<Object, Session>();
    private static Map<Object, Session> appHashMap = new ConcurrentHashMap<Object, Session>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    // 用户id
    private String id;
    // 用户类型
    private String user;

//    public static ChatMessageService chatMessageService; // 消息

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("user") String user, @PathParam("id") String id) throws IOException {
        this.session = session;
        this.id = session.getId();
        this.user = user;
        if (user.equals("admin")) {
            adminHashMap.put(id, session);
        } else if (user.equals("app")) {
            appHashMap.put(session.getId(), session);
        } else {
            return;
        }
        addOnlineCount();           //在线数加1
        try {
            sendMessage("{\"id\":\"\",\"msg\":\"success\"}");
            log.info("有新窗口开始监听:" + id + ",当前在线人数为:" + getOnlineCount());
        } catch (IOException e) {

            log.error("websocket IO Exception");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (user.equals("admin")) {
            Set<Object> objects = adminHashMap.keySet();
            for (Object o : objects) {
                if (o.equals(id)) {
                    adminHashMap.remove(o);
                    log.info("释放的sid为：{}", o);
                    break;
                }
            }
        } else {
            Set<Object> objects = appHashMap.keySet();
            for (Object o : objects) {
                if (o.equals(id)) {
                    appHashMap.remove(o);
                    log.info("释放的sid为：{}", o);
                    break;
                }
            }
        }
        subOnlineCount();           //在线数减1
        //这里写你 释放的时候，要处理的业务
        log.info("有一连接关闭！当前在线人数为" + getOnlineCount());

    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @ Param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        for (Session item : appHashMap.values()) {
            try {
                if (!item.getId().equals(session.getId())){
                    item.getBasicRemote().sendText(message);

                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        log.info("收到来自窗口" + id + "的信息:" + message);
//        ChatMessage chatMessage = new ChatMessage()
//                .setMsgType(this.user)
//                .setContent(message)
//                .setCreateTime(new Date()).setIsRead(BooleanConstant.YES_INTEGER);
//        if (user.equals("admin")) {
//            Message message2 = JSONUtil.strToObj(message, Message.class);
//            chatMessage.setContent(message2.getMsg()).setUserId(message2.getId());
//            if (appHashMap.size() > 0) {
//                Session session = appHashMap.get(message2.getId());
//                try {
//                    if (Objects.nonNull(message2)) {
//                        String dest = message2.getMsg();
//                        if (dest != null) {
//                            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
//                            Matcher m = p.matcher(dest);
//                            dest = m.replaceAll("");
//                        }
//                        message2.setMsg(dest);
//                        session.getBasicRemote().sendText(JSONUtil.objToStr(message2));
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            } else {
//                chatMessage.setIsRead(BooleanConstant.NO_INTEGER);
//            }
//        } else if (user.equals("app")) {
//            chatMessage.setUserId(id);
//            if (adminHashMap.size() > 0) {
//                //群发消息
//                for (Session item : adminHashMap.values()) {
//                    try {
//                        Message message1 = new Message().setId(id).setMsg(message);
//                        item.getBasicRemote().sendText(JSONUtil.objToStr(message1));
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
//            } else {
//                chatMessage.setIsRead(BooleanConstant.NO_INTEGER);
//            }
//        }
//        chatMessageService.save(chatMessage);

    }

    /**
     * @ Param session
     * @ Param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 群发自定义消息
     */
    public static void sendInfo(String message, @PathParam("sid") Integer sid) throws IOException {
        log.info("推送消息到窗口" + sid + "，推送内容:" + message);
        Set<Object> objects = appHashMap.keySet();
        for (Object o : objects) {
            if (o.equals(sid)) {
                Session session = appHashMap.get(o);
                session.getBasicRemote().sendText(message);
                break;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }


}

